package com.fingard.dsp.bank.directbank.citic02.util;

import com.fingard.FGBiz;
import com.lsy.baselib.crypto.algorithm.DESede;
import com.lsy.baselib.crypto.algorithm.RSA;
import com.lsy.baselib.crypto.protocol.PKCS7Signature;
import com.lsy.baselib.crypto.util.Base64;
import com.lsy.baselib.crypto.util.CryptUtil;
import com.lsy.baselib.crypto.util.FileUtil;

import java.io.File;
import java.net.URL;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.X509Certificate;

public class OLPcrypt {
	public static byte[] LinkByteArrays(byte[] arr1, byte[] arr2) {
		int n1 = arr1.length;
		int n2 = arr2.length;
		byte[] newArr = new byte[n1 + n2];
		System.arraycopy(arr1, 0, newArr, 0, n1);
		System.arraycopy(arr2, 0, newArr, n1, n2);
		return newArr;
	}

	public static byte[] LinkByteArrays(byte[] arr1, byte[] arr2, byte[] arr3) {
		int n1 = arr1.length;
		int n2 = arr2.length;
		int n3 = arr3.length;
		byte[] newArr = new byte[n1 + n2 + n3];
		System.arraycopy(arr1, 0, newArr, 0, n1);
		System.arraycopy(arr2, 0, newArr, n1, n2);
		System.arraycopy(arr3, 0, newArr, n1 + n2, n3);
		return newArr;
	}

	public static byte[] LinkByteArrays(byte[] arr1, byte[] arr2, byte[] arr3, byte[] arr4) {
		int n1 = arr1.length;
		int n2 = arr2.length;
		int n3 = arr3.length;
		int n4 = arr4.length;
		byte[] newArr = new byte[n1 + n2 + n3 + n4];
		System.arraycopy(arr1, 0, newArr, 0, n1);
		System.arraycopy(arr2, 0, newArr, n1, n2);
		System.arraycopy(arr3, 0, newArr, n1 + n2, n3);
		System.arraycopy(arr4, 0, newArr, n1 + n2 + n3, n4);
		return newArr;
	}

	public static byte[] sign_crypt2(byte[] srcBytes, String ownKeyStorePwd, String ownKeyStorePath, String ownCertPath,
									 String oppCertPath) {
		try {
			String jarFile =  "file:///" + FGBiz.DSPHOME_Parent+File.separator + "dsp_lib" + File.separator + "bcprov-jdk16-1.46.jar";
			String jarFile1 =  "file:///" + FGBiz.DSPHOME_Parent+File.separator + "dsp_lib" + File.separator + "bcprov-jdk15on-1.59.jar";

			DynamicJarClassLoader classLoader = new DynamicJarClassLoader(new URL[]{new URL(jarFile1)});
			classLoader.clearAssertionStatus();
			classLoader.close();
			classLoader = new DynamicJarClassLoader(new URL[]{new URL(jarFile)},Thread.currentThread().getContextClassLoader().getParent());
			Thread.currentThread().setContextClassLoader(classLoader);


			char[] keyPassword = new String(ownKeyStorePwd).toCharArray();
			byte[] base64EncodedPrivatekey = FileUtil.read4file(ownKeyStorePath);
			PrivateKey signerPrivatekey = CryptUtil.decryptPrivateKey(Base64.decode(base64EncodedPrivatekey),
					keyPassword);
			System.out.println("编译成功。。。。。");

			byte[] base64EncodedCert = FileUtil.read4file(ownCertPath);
			X509Certificate signerCertificate = CryptUtil.generateX509Certificate(Base64.decode(base64EncodedCert));

			byte[] signature = PKCS7Signature.sign(srcBytes, signerPrivatekey, signerCertificate, null, false); // 签名中不附带原文
			String b64StrSignature = new String(Base64.encode(signature));
			byte[] signedMsg = LinkByteArrays(("<signature>" + b64StrSignature + "</signature>").getBytes(), srcBytes); // 带签名的报文

			byte[] sessionKey = DESede.createKey(DESede.DESEDE_KEY_112_BIT); // 产生随机会话密钥明文
			byte[] iv = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
			byte[] cryptMsg = DESede.encrypt(signedMsg, sessionKey, iv); // 签名报文再加密

			byte[] base64EncodedCert2 = FileUtil.read4file(oppCertPath);
			X509Certificate cert2 = CryptUtil.generateX509Certificate(Base64.decode(base64EncodedCert2));
			PublicKey pubKey2 = cert2.getPublicKey();
			byte[] sessionKeyCipher = RSA.encrypt(sessionKey, pubKey2.getEncoded()); // 随机会话密钥密文
			byte[] msgBody = LinkByteArrays("<sessionkey>".getBytes(), Base64.encode(sessionKeyCipher), "</sessionkey>".getBytes(), cryptMsg); // 完整报文体
			byte[] msgHead = String.format("%010dE123456789", 10+msgBody.length).getBytes(); // 报文头,后续信息长度+标识位(P=明文，E=密文)和保留域

			//环境切换成正常依赖
			DynamicJarClassLoader classLoader1 = new DynamicJarClassLoader(new URL[]{new URL(jarFile)});
			classLoader1.clearAssertionStatus();
			classLoader1.close();
			classLoader1 = new DynamicJarClassLoader(new URL[]{new URL(jarFile1)},Thread.currentThread().getContextClassLoader().getParent());
			Thread.currentThread().setContextClassLoader(classLoader1);
			return LinkByteArrays(msgHead, msgBody);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	public static byte[] sign_crypt(byte[] srcBytes, String ownKeyStorePwd, String ownKeyStorePath, String ownCertPath,
			String oppCertPath) {
		try {

			char[] keyPassword = new String(ownKeyStorePwd).toCharArray();
			byte[] base64EncodedPrivatekey = FileUtil.read4file(ownKeyStorePath);
			PrivateKey signerPrivatekey = CryptUtil.decryptPrivateKey(Base64.decode(base64EncodedPrivatekey),
					keyPassword);

			byte[] base64EncodedCert = FileUtil.read4file(ownCertPath);
			X509Certificate signerCertificate = CryptUtil.generateX509Certificate(Base64.decode(base64EncodedCert));

			byte[] signature = PKCS7Signature.sign(srcBytes, signerPrivatekey, signerCertificate, null, false); // 签名中不附带原文
			String b64StrSignature = new String(Base64.encode(signature));
			byte[] signedMsg = LinkByteArrays(("<signature>" + b64StrSignature + "</signature>").getBytes(), srcBytes); // 带签名的报文

			byte[] sessionKey = DESede.createKey(DESede.DESEDE_KEY_112_BIT); // 产生随机会话密钥明文
			byte[] iv = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
			byte[] cryptMsg = DESede.encrypt(signedMsg, sessionKey, iv); // 签名报文再加密

			byte[] base64EncodedCert2 = FileUtil.read4file(oppCertPath);
			X509Certificate cert2 = CryptUtil.generateX509Certificate(Base64.decode(base64EncodedCert2));
			PublicKey pubKey2 = cert2.getPublicKey();
			byte[] sessionKeyCipher = RSA.encrypt(sessionKey, pubKey2.getEncoded()); // 随机会话密钥密文
			byte[] msgBody = LinkByteArrays("<sessionkey>".getBytes(), Base64.encode(sessionKeyCipher),
					"</sessionkey>".getBytes(), cryptMsg); // 完整报文体
			byte[] msgHead = String.format("%010d", msgBody.length).getBytes(); // 报文头,后续信息长度+标识位(P=明文，E=密文)和保留域
			return LinkByteArrays(msgHead, msgBody);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}
}
